﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using MOJsdk;
using TIME = System.Timers;
using System.Threading;
using System.Windows.Threading;

namespace MOJ
{
    /// <summary>
    /// Interaction logic for Control_Toasts.xaml
    /// </summary>
    public partial class Control_Toasts : UserControl
    {
        private int maxNum;
        private int num;
        private Queue<TimeSpanText> _fifo;

        public Control_Toasts()
        {
            InitializeComponent();
            INI();
        }

        private void INI()
        {
            if (!GlobalVars.TheHost.SystemVars.VarExist("MoJToastDuration"))
                GlobalVars.TheHost.SystemVars.SetVar("MoJToastDuration", "2000");

            _panel.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
            maxNum = 10;

            this.Loaded += OnLoaded;
        }
        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            _fifo = new Queue<TimeSpanText>();
            num = 0;
        }
        private void Refresh()
        {
            this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate
            {
                _panel.Children.Clear();
                foreach (var v in _fifo)
                    _panel.Children.Add(v.TextElem);
            });
        }

        public void Add(string text)
        {
            num++;
            if (num == int.MaxValue)
                num = 0;

            TextBlock block = new TextBlock();
            block.Text = text;
            block.Height = 23;
            block.IsHitTestVisible = false;
            block.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
            block.ApplyStyle("0101125");

            TimeSpanText txt = new TimeSpanText(block, GlobalVars.TheHost.SystemVars.GetVar("MoJToastDuration").ToDouble(), num);
            txt.OnExpire += OnExpire;

            if (_fifo.Count == maxNum)
                _fifo.Dequeue();

            _fifo.Enqueue(txt);
            Refresh();
            txt.Start();
        }

        private void OnExpire(object sender)
        {
            TimeSpanText txt = sender as TimeSpanText;
            if (_fifo.Count(z => z.Index == txt.Index) <= 0)
                return;

            _fifo.Dequeue();
            Refresh();
        }

        public void SetMaxElems(int value)
        {
            maxNum = value;
        }
    }

    public class TimeSpanText : IComparable
    {
        private TextBlock _txt;
        private TimeSpan _time;
        private double _milliseconds;
        private TIME.Timer _t;
        private int _index;

        public TimeSpanText(TextBlock TextElement, double MinMilliseconds, int num)
        {
            _txt = TextElement;
            _time = DateTime.Now.TimeOfDay;
            _milliseconds = MinMilliseconds;
            _index = num;

            OnExpire += delegate { };
        }

        public void Start()
        {
            _time = DateTime.Now.TimeOfDay;
            _t = new TIME.Timer(_milliseconds);
            _t.AutoReset = false;
            _t.Elapsed += Expired;
            _t.Start();
        }

        public TextBlock TextElem
        { get { return _txt; } }
        public TimeSpan Time
        { get { return _time; } }
        public bool IsExpired()
        {
            TimeSpan timenow = DateTime.Now.TimeOfDay;
            double pass = timenow.TotalMilliseconds - _time.TotalMilliseconds;
            if (pass >= _milliseconds)
                return true;

            return false;
        }
        public int Index
        { get { return _index; } }

        public int CompareTo(object obj)
        {
            TimeSpanText t2 = obj as TimeSpanText;
            return _txt.Text.CompareTo(t2.TextElem.Text);
        }

        private void Expired(object sender, TIME.ElapsedEventArgs e)
        {
            OnExpire(this);
        }

        public delegate void ExpiredHandler(object sender);
        public event ExpiredHandler OnExpire;
    }
    public class TimeSpanTextComparer : IEqualityComparer<TimeSpanText>
    {

        public bool Equals(TimeSpanText b1, TimeSpanText b2)
        {
            if (b1.TextElem.Text == b2.TextElem.Text)
            {
                return true;
            }
            else
            {
                return false;
            }
        }


        public int GetHashCode(TimeSpanText bx)
        {
            return bx.GetHashCode();
        }
    }
}
